﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.ObjectModel;
using System.Reflection;

namespace Fonlow.CommandLineGui
{

    /// <summary>
    /// Load assemblies with implementations of CommandBase and Options, and create instances of CommandBase
    /// </summary>
    public sealed class TypeLoader
    {
        private TypeLoader()
        {
        }

        /// <summary>
        /// Load assemblies with implementations of IConfigurationRoot, and create instances of IConfigurationRoot
        /// </summary>
        public static CommandBase LoadAssemblyWithCommand(string assemblyName)
        {

            string typeName = typeof(CommandBase).FullName;

                Assembly assembly = null;
                try
                {
                    assembly = Assembly.Load(assemblyName);
                    System.Diagnostics.Trace.WriteLine(String.Format("Assembly {0} is loaded for type {1}.", assemblyName, typeName));
                }
                catch (System.IO.FileLoadException e)
                {
                    System.Diagnostics.Trace.WriteLine(String.Format("When loading {0}, errors occur: {1}", assemblyName, e.Message));
                    return null;
                }
                catch (BadImageFormatException e)
                {
                    System.Diagnostics.Trace.WriteLine(String.Format("When loading {0}, errors occur: {1}", assemblyName, e.Message));
                    //when file is a win32 dll.
                    return null;
                }
                catch (System.IO.FileNotFoundException e)
                {
                    System.Diagnostics.Trace.WriteLine(String.Format("When loading {0}, errors occur: {1}", assemblyName, e.Message));
                    return null;
                }


                try
                {
                    foreach (Type type in assembly.GetTypes())
                    {
                        if ((type.IsClass) && (typeof(CommandBase).IsAssignableFrom(type)))
                        {
                            CommandBase command = (CommandBase)assembly.CreateInstance(type.FullName);
                            if (command != null)
                            {
                                return command;
                            }
                        }
                    }
                }
                catch (ReflectionTypeLoadException e)
                {
                    foreach (Exception ex in e.LoaderExceptions)
                    {
                        System.Diagnostics.Trace.WriteLine(String.Format("When loading {0}, GetTypes errors occur: {1}", assemblyName, ex.Message));
                    }
                }
                catch (TargetInvocationException e)
                {
                    System.Diagnostics.Trace.WriteLine(String.Format("When loading {0}, GetTypes errors occur: {1}", assemblyName, e.Message + "~~" + e.InnerException.Message));
                }

                return null;
        }


    }


}
